# coding:utf-8

import time
import wx.lib.rcsizer as rcs
import matplotlib
import matplotlib.figure
import matplotlib.backends.backend_wxagg
import matplotlib.backends.backend_wx
from mpl_toolkits.axes_grid1.axes_divider import make_axes_area_auto_adjustable
from matplotlib import rcParams
import Config

rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Tahoma']
rcParams['font.size'] = '8'

try:
    from agw import fourwaysplitter as FWS
except ImportError:  # if it's not there locally, try the wxPython lib.
    try:
        import wx.lib.agw.fourwaysplitter as FWS
    except ImportError:
        exit()

# 菜单ID
from AppIds import *

import wx.lib.newevent

# Frame start
SERIAL_GENIUS_FS_CHAR = 0x0F
# Slash
SERIAL_GENIUS_SL_CHAR = 0x1F


# 二维图像模块
class Video(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, style=wx.BORDER_DOUBLE)

        ############# 状态信息 ############
        # 该模块是否启用
        self.isUsing = False

        ############# 配置信息 ############
        self.video_width = 160
        self.video_height = 90
        self.video_data = []
        self.video_data_gray = []
        self.video_gray = True

        self.video1_width = 160
        self.video1_height = 90
        self.video1_data = []
        self.video1_data_gray = []
        self.video1_gray = True

        self.currentShow = 0
        self.recvVideoLength = 0
        self.saveJPG = False

        self.dataBuffer = []
        self.videoDataParseState = 0
        self.videoDataParseRow = 0
        self.videoDataParseCol = 0
        self.videoDataParseRGB = 0

        ############# 开始布局 ###########
        gridSizer = rcs.RowColSizer()
        rowTotal = 3
        colTotal = 4

        # 标题
        title = wx.StaticText(self, -1, u"二维图像")
        title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        gridSizer.Add(title, pos=(0, 0), size=(1, colTotal), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)

        # 绘图区
        self.figure = matplotlib.figure.Figure(figsize=(1, 1))
        self.figure.subplots_adjust(left=0.00, bottom=0.00, right=1.00, top=1.00, wspace=None, hspace=None)
        self.axes = self.figure.add_subplot(111)
        self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg(self, 20, self.figure)
        gridSizer.Add(self.canvas, pos=(1, 0), size=(1, colTotal), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
        make_axes_area_auto_adjustable(self.axes)

        # 测试绘图        
        self.axes.imshow([[[1.0, 1.0, 1.0] for col in range(160)] for row in range(90)])

        # 清空
        btn = wx.Button(self, -1, u"清空")
        self.Bind(wx.EVT_BUTTON, self.OnClearData, btn)
        gridSizer.Add(btn, pos=(2, 0), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        # 保存
        btn = wx.Button(self, -1, u"保存")
        self.Bind(wx.EVT_BUTTON, self.OnSaveData, btn)
        gridSizer.Add(btn, pos=(2, 1), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        # 显示接收到图像帧数
        self.labelVideoLength = wx.StaticText(self, -1, u"接收帧数：0")
        gridSizer.Add(self.labelVideoLength, pos=(2, 2), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        # 保存到JPG文件
        ck = wx.CheckBox(self, -1, u"同时保存到JPG")
        ck.Bind(wx.EVT_CHECKBOX, self.OnSaveJpg)
        gridSizer.Add(ck, pos=(2, 3), size=(1, 1), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
        if Config.APP_CONFIG['module_video']['saveJpg'] == '1':
            ck.SetValue(True)
            self.saveJPG = True

        # 设置变宽信息
        gridSizer.AddGrowableCol(2)
        gridSizer.AddGrowableRow(1)

        ############# 结束布局 ###########
        self.SetSizer(gridSizer)
        self.SetAutoLayout(True)

        # 更新GUI数据的线程
        (self.UpdateDataEvent, self.UPDATA_DATA_EVENT) = wx.lib.newevent.NewEvent()
        self.Bind(self.UPDATA_DATA_EVENT, self.RefreshVideo)

    # 是否保存到JPG
    def OnSaveJpg(self, event):
        if event.GetEventObject().GetValue():
            self.saveJPG = True
            Config.APP_CONFIG['module_video']['saveJpg'] = '1'
        else:
            self.saveJPG = False
            Config.APP_CONFIG['module_video']['saveJpg'] = '0'

    # 是否保存到JPG
    def OnSaveData(self, event):
        self.canvas.print_jpg(time.strftime('Video_static_%Y%m%d_%H_%M_%S.jpg', time.localtime(time.time())))
        wx.MessageBox(u'保存成功')

    # 新增串口数据，被串口接收所调用
    def RecvData(self, data):
        self.dataBuffer.extend(data)
        while (self.videoDataParseState == 0 and len(self.dataBuffer) >= 9) or \
                (self.videoDataParseState == 1 and len(self.dataBuffer) > 0):
            try:
                if self.videoDataParseState == 0:
                    # 找到帧头
                    while len(self.dataBuffer) > 1:
                        if self.dataBuffer[0] == SERIAL_GENIUS_FS_CHAR:
                            break
                        if self.dataBuffer[0] == SERIAL_GENIUS_SL_CHAR:
                            self.dataBuffer.pop(0)
                        self.dataBuffer.pop(0)

                    if len(self.dataBuffer) < 9:
                        break

                    # 0F 命令 长度 校验 宽度H 宽度L 高度H 高度L 颜色模式...

                    # 找到帧头
                    if self.dataBuffer[0] == SERIAL_GENIUS_FS_CHAR:
                        if self.dataBuffer[1] == 0x0D:
                            if self.dataBuffer[3] == self.dataBuffer[1] ^ self.dataBuffer[2]:
                                self.videoDataParseState = 1

                                valueH = self.dataBuffer[4]
                                valueL = self.dataBuffer[5]
                                width = (valueH << 8) | valueL

                                valueH = self.dataBuffer[6]
                                valueL = self.dataBuffer[7]
                                height = (valueH << 8) | valueL

                                mode = self.dataBuffer[8]

                                if 0 < width <= 1000 and 0 < height <= 1000 and 1 <= mode <= 2:
                                    # print width, height, mode
                                    if self.currentShow == 0:

                                        self.video1_width = width
                                        self.video1_height = height
                                        if mode == 2:
                                            self.video1_gray = True
                                        else:
                                            self.video1_gray = False

                                    elif self.currentShow == 1:

                                        self.video_width = width
                                        self.video_height = height
                                        if mode == 2:
                                            self.video_gray = True
                                        else:
                                            self.video_gray = False

                                    # 根据发送过来的图像头信息初始化数组
                                    self.InitVideoData()

                                    # 初始化接收行列
                                    self.videoDataParseRow = 0
                                    self.videoDataParseCol = 0
                                    self.videoDataParseRGB = 0

                                    # 弹出已经初始化的数据
                                    for i in range(0, 9):
                                        self.dataBuffer.pop(0)

                                    self.videoDataParseState = 1
                                else:
                                    # 错误的帧数据
                                    for i in range(0, 9):
                                        self.dataBuffer.pop(0)
                            else:
                                # 数据校验出错
                                self.dataBuffer.pop(0)
                                self.dataBuffer.pop(0)
                                self.dataBuffer.pop(0)
                                self.dataBuffer.pop(0)
                        else:
                            # 不是我们的数据
                            self.dataBuffer.pop(0)
                            self.dataBuffer.pop(0)
                            self.dataBuffer.pop(0)
                            self.dataBuffer.pop(0)
                    else:
                        # 不是一个帧头，在这里忽略
                        self.dataBuffer.pop(0)

                elif self.videoDataParseState == 1:
                    if self.dataBuffer[0] == SERIAL_GENIUS_SL_CHAR and len(self.dataBuffer) < 2:
                        break

                    # 解析数据
                    data = self.GetNextDataByte()
                    if self.currentShow == 0:
                        if self.video1_gray:
                            self.video1_data[self.videoDataParseRow][self.videoDataParseCol] = [data / 255.0,
                                                                                                data / 255.0,
                                                                                                data / 255.0]

                            self.videoDataParseCol += 1

                            if self.videoDataParseCol == self.video1_width:
                                self.videoDataParseRow += 1
                                self.videoDataParseCol = 0

                                if self.videoDataParseRow == self.video1_height:
                                    # 发送更新图像事件
                                    wx.PostEvent(self, self.UpdateDataEvent(frame=0))
                                    self.currentShow = 1
                                    self.videoDataParseState = 0
                        else:
                            self.video1_data[self.videoDataParseRow][self.videoDataParseCol][
                                self.videoDataParseRGB] = data / 255.0

                            self.videoDataParseRGB += 1

                            if self.videoDataParseRGB == 3:
                                self.videoDataParseCol += 1
                                self.videoDataParseRGB = 0

                                if self.videoDataParseCol == self.video1_width:
                                    self.videoDataParseRow += 1
                                    self.videoDataParseCol = 0

                                    if self.videoDataParseRow == self.video1_height:
                                        # 发送更新图像事件
                                        wx.PostEvent(self, self.UpdateDataEvent(frame=0))
                                        self.currentShow = 1
                                        self.videoDataParseState = 0


                    elif self.currentShow == 1:
                        if self.video_gray:
                            self.video_data[self.videoDataParseRow][self.videoDataParseCol] = [data / 255.0,
                                                                                               data / 255.0,
                                                                                               data / 255.0]

                            self.videoDataParseCol += 1

                            if self.videoDataParseCol == self.video_width:
                                self.videoDataParseRow += 1
                                self.videoDataParseCol = 0

                                if self.videoDataParseRow == self.video_height:
                                    # 发送更新图像事件
                                    wx.PostEvent(self, self.UpdateDataEvent(frame=1))
                                    self.currentShow = 0
                                    self.videoDataParseState = 0
                        else:
                            self.video_data[self.videoDataParseRow][self.videoDataParseCol][
                                self.videoDataParseRGB] = data / 255.0

                            self.videoDataParseRGB += 1

                            if self.videoDataParseRGB == 3:
                                self.videoDataParseCol += 1
                                self.videoDataParseRGB = 0

                                if self.videoDataParseCol == self.video_width:
                                    self.videoDataParseRow += 1
                                    self.videoDataParseCol = 0

                                    if self.videoDataParseRow == self.video_height:
                                        # 发送更新图像事件
                                        wx.PostEvent(self, self.UpdateDataEvent(frame=1))
                                        self.currentShow = 0
                                        self.videoDataParseState = 0
            except:
                self.videoDataParseState = 0
                break

    # 获取数据部分中下一个数据（如果转义自动去除转义符号）
    def GetNextDataByte(self):
        if self.dataBuffer[0] == SERIAL_GENIUS_SL_CHAR:
            self.dataBuffer.pop(0)
        return self.dataBuffer.pop(0)

    # 刷新视频数据，从变量中显示到图形中
    def RefreshVideo(self, event):
        if event.frame == 0:
            self.axes.imshow(self.video1_data, interpolation='nearest')

        elif event.frame == 1:
            self.axes.imshow(self.video_data, interpolation='nearest')

        self.axes.grid(True)

        self.recvVideoLength += 1
        self.labelVideoLength.SetLabel(u'图像帧数: ' + str(self.recvVideoLength))
        self.canvas.draw()
        # Save JPG
        if self.saveJPG:
            self.canvas.print_jpg('Video_' + str(self.recvVideoLength) + time.strftime('_%Y%m%d_%H_%M_%S.jpg',
                                                                                       time.localtime(time.time())))

    # 初始化二维图像数据
    def InitVideoData(self):
        if self.currentShow == 0:
            self.video1_data = [[[1.0, 1.0, 1.0] for col in range(self.video1_width)] for row in
                                range(self.video1_height)]
        elif self.currentShow == 1:
            self.video_data = [[[1.0, 1.0, 1.0] for col in range(self.video_width)] for row in
                               range(self.video_height)]

    # 清空数据
    def OnClearData(self, event):
        self.recvVideoLength = 0
        self.labelVideoLength.SetLabel(u'图像帧数: ' + str(self.recvVideoLength))
        self.axes.imshow([[[1.0, 1.0, 1.0] for col in range(160)] for row in range(90)])
        self.canvas.draw()
        self.axes.grid(True)

    # 重绘函数
    def OnPaint(self, event):
        self.canvas.draw()
